package com.hoperun.checkcloth.viewmodel

import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableField
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.hadilq.liveevent.LiveEvent
import com.hoperun.checkcloth.R
import com.hoperun.checkcloth.net.ApiError
import com.hoperun.checkcloth.net.ClothFlawInfo
import com.hoperun.checkcloth.net.DictItem
import com.hoperun.checkcloth.repository.Repository
import com.hoperun.checkcloth.util.Logger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext


class LeftOverBoltClothViewModel : ViewModel() {
    private val logger = Logger.create("LeftOverBoltViewModel")

    private val _messageRes = LiveEvent<Int>()
    val messageRes: LiveData<Int> = _messageRes
    private val _message = LiveEvent<String>()
    val message: LiveData<String> = _message
    private val _dialogMessage = LiveEvent<String>()
    val dialogMessage: LiveData<String> = _dialogMessage
    private val _dialogMessageRes = LiveEvent<Int>()
    val dialogMessageRes: LiveData<Int> = _dialogMessageRes

    private val _flawTypes: MutableLiveData<List<DictItem>> = MutableLiveData()
    val flawTypes: LiveData<List<DictItem>> = _flawTypes

    private val _remarks: MutableLiveData<List<DictItem>> = MutableLiveData()
    val remarks: LiveData<List<DictItem>> = _remarks

    private val _commit = LiveEvent<Boolean>()
    val commit: LiveData<Boolean> = _commit

    private val _loading = LiveEvent<Boolean>()
    val loading: LiveData<Boolean> = _loading

    // 信息列表
    private val _flawInfoList: MutableLiveData<List<ClothFlawInfo>> = MutableLiveData()
    val flawInfoList: LiveData<List<ClothFlawInfo>> = _flawInfoList
    private val _cacheFlawInfo: MutableList<ClothFlawInfo> = mutableListOf()

    // 设置数目事件
    private val _setCount = LiveEvent<ClothFlawInfo>()
    val setCount: LiveData<ClothFlawInfo> = _setCount

    // 员工姓名
    val workerName = ObservableField<String>()

    // 布号
    val clothNo = ObservableField<String>()

    // 类型 tab 是否被选中
    val showTypeTab = ObservableBoolean(true)

    // 三联单号是否校验通过
    private var monadNoPass = false

    // debug text
    val debugText = ObservableField<String>()

    fun loadData() {
        workerName.set(Repository.leftOverSystemInfo?.workerName)

        viewModelScope.launch {
            Repository.requestLeftOverBoltDataDict()?.let { (types, remarks) ->
                _flawTypes.value = types
                _remarks.value = remarks
                // 初始默认选中类型 Tab
                showTypeTab.set(true)
            }
        }
    }

    /***
     *  类型列表中的条目被点击，要给信息列表里添加新的类型条目，如果该类型已存在则数量加一
     */
    fun onFlawTypeItemClick(item: DictItem) {
        updateFlawInfoList {
            addFlawInfoItemNumber(item, increase = true)
        }
    }

    /***
     *  备注列表中的条目被点击，要给信息列表里添加新的类型条目，如果该类型已存在则数量加一
     */
    fun onRemarkItemClick(item: DictItem) {
        updateFlawInfoList {
            addFlawInfoItemNumber(item, increase = true)
        }
    }

    private fun updateFlawInfoList(block: suspend () -> Unit) = viewModelScope.launch {
        block()
        _flawInfoList.value = _cacheFlawInfo
    }

    /***
     *  给信息列表里添加新的类型条目
     *
     *  @param item 类型条目
     *  @param number 制定的数量，会和已有的条目数量相加再赋值给条目
     *  @param increase 是否增量添加数量
     */
    private suspend fun addFlawInfoItemNumber(item: DictItem, number: Int = 1, increase: Boolean = false) = withContext(Dispatchers.IO) {
        _cacheFlawInfo.find { it.id == item.key }?.let {
            _cacheFlawInfo[_cacheFlawInfo.indexOf(it)] = if (increase) it inc number else it set number
            return@withContext
        }

        _cacheFlawInfo.add(0, ClothFlawInfo(item.key, item.value, number))
    }


    /***
     *  当信息列表中条目被删除
     */
    fun onFlawInfoItemDelete(item: ClothFlawInfo) {
        updateFlawInfoList {
            deleteFlawInfoList(item)
        }
    }

    /***
     *  删除列表的条目
     */
    private suspend fun deleteFlawInfoList(item: ClothFlawInfo) = withContext(Dispatchers.IO) {
        if (_cacheFlawInfo.contains(item)) {
            _cacheFlawInfo.remove(item)
        }
    }

    /***
     *  当信息列表中条目的数目设置被点击时
     */
    fun onFlawInfoSetCountClick(item: ClothFlawInfo) {
        _setCount.value = item
    }

    /***
     *  设置信息列表中条目的数目
     */
    fun onSetFlawInfoCount(item: ClothFlawInfo, count: Int) {
        updateFlawInfoList {
            // 相当于给信息列表里添加已有的类型条目，并指定数量
            addFlawInfoItemNumber(DictItem(item.id, item.name), count)
        }
    }

    fun onClothNoEditTextChanged() {
        viewModelScope.launch {
            clearData()
        }
    }

    /***
     *  根据三联单号获取信息
     */
    fun requestInformation(monadNo: String) {
        viewModelScope.launch {
            _loading.value = true

            if (monadNo.length <= 4) {
                _dialogMessage.value = "三联单号格式不正确，请重新扫描"
                return@launch
            }


            val result = Repository.requestLeftOverBoltInformation(monadNo)
            if (result.state is ApiError) {
                clearData()
                _dialogMessage.value = result.errMessage
            } else {
                // 验证通过
                monadNoPass = true

                result.data?.first?.let {
                    if (it.isNotEmpty()) {
                        _message.value = it
                    }
                }

                result.data?.second?.let {
                    _cacheFlawInfo.clear()
                    _cacheFlawInfo.addAll(it)
                    _flawInfoList.value = _cacheFlawInfo
                }

                result.data?.third?.let {
                    clothNo.set(it.bbZZ)
                }
            }
        }.invokeOnCompletion { _loading.value = false }
    }

    fun onCommitButtonClick(monadNo: String) {
        if (monadNo.trim().isEmpty()) {
            _dialogMessage.value = "三联单号不能为空"
            return
        }

        if (monadNoPass.not()) {
            _dialogMessageRes.value = R.string.monadno_checked_fail_and_tray_again
            return
        }

        viewModelScope.launch {
            if (Repository.commitLeftOverBoltFlawInformation(monadNo, _cacheFlawInfo)) {
                _cacheFlawInfo.clear()
                clothNo.set(null)
                _flawInfoList.value = _cacheFlawInfo
                _commit.value = true
            } else {
                _dialogMessageRes.value = R.string.commit_failed
                _commit.value = false
            }
        }

    }

    /***
     *  当类型按钮被点击事件
     */
    fun onFlawTypeButtonClick() {
        showTypeTab.set(true)
    }

    /***
     *  当备注按钮被点击事件
     */
    fun onFlawRemarkButtonClick() {
        showTypeTab.set(false)
    }


    /***
     *  清空数据
     */
    private fun clearData() {
        clothNo.set(null)
        _cacheFlawInfo.clear()
        _flawInfoList.value = _cacheFlawInfo
        // 并且要验证才能提交
        monadNoPass = false
    }
}